/*
 * @Author: Wangjun
 * @Date: 2021-05-30 10:57:40
 * @LastEditTime: 2022-09-14 18:27:09
 * @LastEditors: Wangjun
 * @Description:统计函数
 * @FilePath: \query\statistical.go
 * hnxr
 */

package query

import (
	"errors"
	"fmt"
	"reflect"

	"gitee.com/haodreams/libs/easy"
)

/**
 * @description: 最大值
 * @param {string} key
 * @return {*}
 */
func (m *Table) Max(key string) (val interface{}, err error) {
	v := reflect.ValueOf(m.arrayObject)
	n, valueType, ids, err := m.checkPreconditions(v, key)
	if err != nil {
		return
	}

	isFirst := true
	floatValue := 0.0
	intValue := int64(0)
	stringValue := ""
	for i := 0; i < n; i++ {
		field := v.Index(i)
		elem, ok := m.checkField(field, ids)
		if !ok {
			continue
		}
		switch valueType {
		case easy.TypeFloat:
			fval, err := easy.GetFloat64(elem.Interface())
			if err != nil {
				continue
			}
			if isFirst {
				floatValue = fval
				isFirst = false
				continue
			}
			if fval > floatValue {
				floatValue = fval
			}
		case easy.TypeInt:
			ival, err := easy.GetInt64(elem.Interface())
			if err != nil {
				continue
			}
			if isFirst {
				intValue = ival
				isFirst = false
				continue
			}
			if float64(ival) > floatValue {
				intValue = ival
			}
		case easy.TypeString:
			s := elem.String()
			if isFirst {
				stringValue = s
				isFirst = false
				continue
			}
			if s > stringValue {
				stringValue = s
			}
		default:
			continue
		}
	}
	if isFirst {
		return nil, errors.New("无数据")
	}

	switch valueType {
	case easy.TypeFloat:
		return floatValue, nil
	case easy.TypeInt:
		return intValue, nil
	case easy.TypeString:
		return stringValue, nil
	}
	return nil, errors.New("类型不支持")
}

/**
 * @description: 最小值
 * @param {string} key
 * @return {*}
 */
func (m *Table) Min(key string) (val interface{}, err error) {
	v := reflect.ValueOf(m.arrayObject)
	n, valueType, ids, err := m.checkPreconditions(v, key)
	if err != nil {
		return
	}

	isFirst := true
	floatValue := 0.0
	intValue := int64(0)
	stringValue := ""
	for i := 0; i < n; i++ {
		field := v.Index(i)
		elem, ok := m.checkField(field, ids)
		if !ok {
			continue
		}
		switch valueType {
		case easy.TypeFloat:
			fval, err := easy.GetFloat64(elem.Interface())
			if err != nil {
				continue
			}
			if isFirst {
				floatValue = fval
				isFirst = false
				continue
			}
			if fval < floatValue {
				floatValue = fval
			}
		case easy.TypeInt:
			ival, err := easy.GetInt64(elem.Interface())
			if err != nil {
				continue
			}
			if isFirst {
				intValue = ival
				isFirst = false
				continue
			}
			if float64(ival) < floatValue {
				intValue = ival
			}
		case easy.TypeString:
			s := elem.String()
			if isFirst {
				stringValue = s
				isFirst = false
				continue
			}
			if s < stringValue {
				stringValue = s
			}
		default:
			continue
		}
	}

	if isFirst {
		return nil, errors.New("无数据")
	}

	switch valueType {
	case easy.TypeFloat:
		return floatValue, nil
	case easy.TypeInt:
		return intValue, nil
	case easy.TypeString:
		return stringValue, nil
	}
	return nil, errors.New("类型不支持")
}

/**
 * @description: 统计数量
 * @param {string} key
 * @return {*}
 */
func (m *Table) Count(key string) (val int, err error) {
	v := reflect.ValueOf(m.arrayObject)
	return v.Len(), nil
}

/**
 * @description: 求和
 * @param {string} key
 * @return {*}
 */
func (m *Table) Sum(key string) (val interface{}, err error) {
	v := reflect.ValueOf(m.arrayObject)
	n, valueType, ids, err := m.checkPreconditions(v, key)
	if err != nil {
		return
	}

	if valueType == easy.TypeString {
		err = errors.New("类型不支持")
		return 0, err
	}

	floatValue := 0.0
	for i := 0; i < n; i++ {
		field := v.Index(i)
		elem, ok := m.checkField(field, ids)
		if !ok {
			continue
		}

		fval, err := easy.GetFloat64(elem.Interface())
		if err != nil {
			continue
		}
		floatValue += fval

		// if floatValue < -1000000 {
		// 	log.Println("========> -1000000", fval, floatValue)
		// }
	}

	return floatValue, nil
}

/**
 * @description: 平均值
 * @param {string} key
 * @return {*}
 */
func (m *Table) Avg(key string) (val interface{}, err error) {
	v := reflect.ValueOf(m.arrayObject)
	n, valueType, ids, err := m.checkPreconditions(v, key)
	if err != nil {
		return
	}

	if valueType == easy.TypeString {
		err = errors.New("类型不支持")
		return 0, err
	}

	count := 0
	floatValue := 0.0
	for i := 0; i < n; i++ {
		field := v.Index(i)
		elem, ok := m.checkField(field, ids)
		if !ok {
			continue
		}

		fval, err := easy.GetFloat64(elem.Interface())
		if err != nil {
			continue
		}
		floatValue += fval
		count++
	}

	if count > 0 {
		return floatValue / float64(count), nil
	}
	return 0, errors.New("无数据")
}

/**
 * @description:获取某列的值
 * @param {string} key
 * @return {*}
 */
func (m *Table) Column(key string) (val float64, err error) {
	v := reflect.ValueOf(m.arrayObject)
	n, valueType, ids, err := m.checkPreconditions(v, key)
	if err != nil {
		return
	}
	if valueType == easy.TypeString {
		err = errors.New("类型不支持")
		return 0, err
	}
	if n > 1 {
		err = fmt.Errorf("必须只能有一条数据")
		return 0, err
	} else if n == 0 {
		return 0, errors.New("无数据")
	}
	field := v.Index(0)
	elem, ok := m.checkField(field, ids)
	if !ok {
		return
	}
	val, err = easy.GetFloat64(elem.Interface())
	if err != nil {
		return
	}
	return
}
